package cc.eddic.practice.concurrency.impl;

import cc.eddic.practice.concurrency.LogItem;
import cc.eddic.practice.concurrency.LogItemParser;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LogItemParserCxyImpl implements LogItemParser {


    private LocalDateTime parseDateTime(String dateTimeString) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MMM/yyyy:HH:mm:ss Z", Locale.ENGLISH);
        return LocalDateTime.parse(dateTimeString, formatter);
    }


    private static final Pattern pattern = Pattern.compile(

            "(?<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)\\s+[\\w\\-]+\\s+[\\w\\-]+\\s+\\[" +
                    "(?<time>\\d+/\\w+/\\d+:\\d+:\\d+:\\d+\\s+\\+\\d+)]\\s+\"" +
                    "(?<request>.*)\"\\s+" +
                    "(?<status>\\d+)\\s+" +
                    "(?<bytes>\\d+)\\s+\"" +
                    "(?<referer>[^\"]+)\"\\s+\"" +
                    "(?<ua>[^\"]+)\"");


    @Override
    public Optional<LogItem> parse(String line) {
        Matcher matcher = pattern.matcher(line);
        if (matcher.find()) {
            String ip = matcher.group("ip");
            LocalDateTime time = parseDateTime(matcher.group("time"));
            String request = matcher.group("request");
            int status = Integer.parseInt(matcher.group("status"));
            long bytes = Long.parseLong(matcher.group("bytes"));
            String referer = matcher.group("referer");
            String userAgent = matcher.group("ua");

            String[] requestDetails = parseRequest(request);

            String method = requestDetails[0];
            String path = requestDetails[1];
            String protocol = requestDetails[2];

            LogItem logItem = new LogItem(ip, time, request, method, path, null, protocol, status, bytes, referer, userAgent);
            return Optional.of(logItem);

        }
        return Optional.empty();
    }


    private String[] parseRequest(String request) {
        Matcher matcher = REQUEST_PATTERN.matcher(request);
        if (matcher.matches()) {
            String method = matcher.group("method");
            String url = matcher.group("url");
            String protocol = matcher.group("protocol");

            String path;
            if (url.contains("?")) {
                int index = url.indexOf('?');
                path = url.substring(0, index);
            } else {
                path = url;
            }

            return new String[]{method, path, protocol};
        }

        return new String[]{null, null, null};

    }

    private static final Pattern REQUEST_PATTERN = Pattern.compile(
            "(?<method>\\w+)\\s+" +
                    "(?<url>[^ ]+)\\s+" +
                    "(?<protocol>[^ ]+)");


}
